package grape.attend.service.user.clock;

import cn.hutool.core.date.DateUnit;
import grape.attend.service.user.api.IUserClockService;
import grape.attend.service.user.po.UserClock;
import grape.composite.service.workcalendar.po.WorkCalendar;
import grape.common.tools.ToolService;
import org.springframework.stereotype.Component;

/**
 * 用户上班打卡类型支持服务
 * Created by yangwei
 * Created at 2020/5/26 16:25
 */
@Component
public class UserClockOnClockService implements ToolService {

    /**
     * 正常打卡
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock normalClock(PreClockParam preClockParam,UserClock userClock) {
        Long shouldClockAt = preClockParam.getClasseStartAt();
        CalendarHandleDto calendarHandleDto = calendarHandle(preClockParam, userClock,shouldClockAt);
        if (calendarHandleDto.getIsReturn()) {
            return userClock;
        }else if (calendarHandleDto.getShouldClockAt() != null) {
            shouldClockAt = calendarHandleDto.getShouldClockAt();
        }
        // 迟到
        if(preClockParam.getNow() > shouldClockAt){

            Integer lateTime = IUserClockService.getIntervalMinutes(preClockParam.getNow() , shouldClockAt);
            // 如果设置了下班晚走第二天可以晚到,且上一个班次晚走了
            if (preClockParam.getClock().getIsNextDayLate()
                    && preClockParam.getPreUserClock() != null
                    && preClockParam.getPreUserClock().getIsOffClockLateLeave()) {
                shouldClockAt += preClockParam.getClock().getLateArriveMax() * DateUnit.MINUTE.getMillis();
                // 晚到时间大于设定时间，算迟到
                if (lateTime > preClockParam.getClock().getLateArriveMax()) {
                    userClock.setIsOnClockLate(true);
                    userClock.setOnClockLateTime(lateTime - preClockParam.getClock().getLateArriveMax());
                    userClock.setIsOnClockLateArrive(true);
                    userClock.setOnClockLateArrive(lateTime);
                }else {
                    // 标记为上班晚到了，但打卡正常
                    userClock.setIsOnClockLateArrive(true);
                    userClock.setOnClockLateArrive(lateTime);
                }
            }else {
                userClock.setIsOnClockLate(true);
                userClock.setOnClockLateTime(lateTime);
            }
        }
        userClock.setOnClockShouldAt(shouldClockAt);
        return userClock;
    }

    /**
     * 早到早走，晚到晚走
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock allowEarlEarlyLateLate(PreClockParam preClockParam,UserClock userClock) {
        long shouldClockAt = preClockParam.getClasseStartAt();
        CalendarHandleDto calendarHandleDto = calendarHandle(preClockParam, userClock,shouldClockAt);
        if (calendarHandleDto.getIsReturn()) {
            return userClock;
        }else if (calendarHandleDto.getShouldClockAt() != null) {
            shouldClockAt = calendarHandleDto.getShouldClockAt();
        }

        // 对比按正常打卡时间，比正常打卡时间晚则可能是迟到
        if(preClockParam.getNow() > shouldClockAt){
            Integer lateTime = IUserClockService.getIntervalMinutes(preClockParam.getNow() , shouldClockAt);
            // 如果迟到时间大于设置的最大晚到时间，可能是迟到
            // 如果设置了下班晚走第二天可以晚到
            if (preClockParam.getClock().getIsNextDayLate()
                    && preClockParam.getPreUserClock() != null
                    && preClockParam.getPreUserClock().getIsOffClockLateLeave()) {
                shouldClockAt += (preClockParam.getClock().getLateArriveMax() + preClockParam.getClock().getLateArrive()) * DateUnit.MINUTE.getMillis();
                // 当前设置规则下，上一个班次晚走了，当前上班打卡可以晚到，但迟到时间不能大于两个晚到的时间之和
                if(lateTime > preClockParam.getClock().getLateArriveMax() + preClockParam.getClock().getLateArrive()){
                    userClock.setIsOnClockLate(true);
                    userClock.setOnClockLateTime(lateTime - (preClockParam.getClock().getLateArriveMax() + preClockParam.getClock().getLateArrive()));
                    userClock.setIsOnClockLateArrive(true);
                    userClock.setOnClockLateArrive(lateTime - preClockParam.getClock().getLateArriveMax());
                }else {
                    // 如果迟到时间大于晚到时间（早到早走晚到晚走），标记为晚到
                    if (lateTime >  preClockParam.getClock().getLateArriveMax()) {
                        userClock.setIsOnClockLateArrive(true);
                        userClock.setOnClockLateArrive(lateTime - preClockParam.getClock().getLateArriveMax());
                    }
                }
            }else {
                shouldClockAt += (preClockParam.getClock().getLateArriveMax()) * DateUnit.MINUTE.getMillis();
                if(lateTime > preClockParam.getClock().getLateArriveMax()){
                    userClock.setIsOnClockLate(true);
                    userClock.setOnClockLateTime(lateTime - preClockParam.getClock().getLateArriveMax());
                }

            }
        }
        userClock.setOnClockShouldAt(shouldClockAt);
        return userClock;
    }

    /**
     * 可以早走晚到几分钟
     * @param preClockParam
     * @param userClock
     * @return
     */
    public UserClock allowEarlLate(PreClockParam preClockParam,UserClock userClock) {
        long shouldClockAt = preClockParam.getClasseStartAt();
        return allowEarlEarlyLateLate(preClockParam, userClock);
    }

    /**
     * 工作日历设置考虑
     * @param preClockParam
     * @param userClock
     * @param shouldClockAt
     * @return
     */
    private CalendarHandleDto calendarHandle(PreClockParam preClockParam,UserClock userClock,Long shouldClockAt){
        CalendarHandleDto calendarHandleDto = new CalendarHandleDto();
        calendarHandleDto.setShouldClockAt(shouldClockAt);
        // 如果班次日期休息，不算迟到
        if (preClockParam.getClasseDatewWorkCalendar() != null) {
            // 设置了全天休息，打卡正常
            if (preClockParam.getClasseDateType().name().equals(WorkCalendar.Type.all_day_rest.name())) {
                calendarHandleDto.setIsReturn(true);
            }
            // 设置了上午休息，那么打卡时间应该在结束休息之前
            else  if (preClockParam.getClasseDateType().name().equals(WorkCalendar.Type.day_am_rest_pm_work.name())) {
                if (preClockParam.getClasse().getIsHasRest()) {
                    calendarHandleDto.setShouldClockAt(preClockParam.getClasseRestEndAt());
                }else {
                    // 如果没有设置休息，那么打卡时间延长工作时长的一半
                    calendarHandleDto.setShouldClockAt(shouldClockAt + (preClockParam.getClasseEndAt() - preClockParam.getClasseStartAt())/2);
                }
            }
        }else {

            // 如果没有设置，按自然日，不是工作日正常
            if(!preClockParam.getClasseDateDateType().name().equals(WorkCalendar.DateType.date_type_work.name())){
                calendarHandleDto.setIsReturn(true);
            }
        }
        userClock.setOnClockShouldAt(calendarHandleDto.getShouldClockAt());
        return calendarHandleDto;
    }
}
